package com.yao2san.sim.storage.client.core.integrate;

import com.aliyun.oss.OSS;
import com.qcloud.cos.COSClient;
import com.yao2san.sim.storage.client.config.*;
import com.yao2san.sim.storage.client.core.auth.Credentials;
import com.yao2san.sim.storage.client.core.enums.StorageType;
import com.yao2san.sim.storage.client.core.manager.*;
import com.yao2san.sim.storage.client.exception.StorageInstanceNotFoundException;
import io.minio.MinioClient;

import java.io.IOException;
import java.util.List;
import java.util.ServiceLoader;

import static com.yao2san.sim.storage.client.core.enums.StorageType.*;
import static com.yao2san.sim.storage.client.core.integrate.IntegrateAdapterUtil.getClient;
import static com.yao2san.sim.storage.client.core.integrate.IntegrateAdapterUtil.getProperties;

/**
 * @author wxg
 **/
public class IntegrateStorageManager extends AbstractIntegrateStorageManager {
    private final SimStorageClientProperties clientProperties;

    private final IntegrateConfig integrateConfig;
    private StorageManager storageManager;

    public IntegrateStorageManager(SimStorageClientProperties clientProperties, IntegrateConfig integrateConfig) {
        this.clientProperties = clientProperties;
        this.integrateConfig = integrateConfig;
        this.storageManager = getStorageManager();
    }

    @Override
    public boolean exist(String object) {
        return storageManager.exist(object);
    }

    @Override
    public void delete(String object) throws IOException {
        storageManager.delete(object);
    }

    @Override
    public void rename(String source, String target) throws IOException {
        storageManager.rename(source, target);
    }

    @Override
    public void copy(String source, String target, boolean keepSource) throws IOException {
        storageManager.copy(source, target, keepSource);
    }

    @Override
    public List<StorageObject> list(String prefix) throws IOException {
        return list(prefix, null);
    }

    @Override
    public List<StorageObject> list(String prefix, String startAfter) throws IOException {
        return storageManager.list(prefix, startAfter);
    }

    private StorageManager getStorageManager() {
        StorageManager storageManager = null;
        StorageType storageType = integrateConfig.getStorageType();
        if (storageType == null) {
            throw new StorageInstanceNotFoundException("Not found storage manager from open id: " + integrateConfig.getIntegrateProperties().getOpenId() + ", please check your config");
        }
        if (storageType.equals(LOCAL)) {
            return new LocalStorageManager((LocalProperties) getProperties(integrateConfig));
        }
        if (storageType.equals(MINIO)) {
            return new MinioStorageManager((MinioClient) getClient(integrateConfig), (MinioProperties) getProperties(integrateConfig));
        }
        if (storageType.equals(ALI_OSS)) {
            return new AliOssStorageManager((OSS) getClient(integrateConfig), (AliOssProperties) getProperties(integrateConfig));
        }
        if (storageType.equals(TENCENT_COS)) {
            return new TencentCosStorageManager((COSClient) getClient(integrateConfig), (TencentCosProperties) getProperties(integrateConfig));
        }

        //custom storage type with spi
        if (storageType.equals(CUSTOM)) {
            String customType = clientProperties.getCustomType();
            if (customType == null || customType.isEmpty()) {
                throw new IllegalArgumentException("Custom type can not be empty, please check your config");
            }
            ServiceLoader<StorageManager> serviceLoader = ServiceLoader.load(StorageManager.class);
            for (StorageManager service : serviceLoader) {
                if (customType.equalsIgnoreCase(service.getName())) {
                    storageManager = service;
                    break;
                }
            }
            if (storageManager == null) {
                throw new StorageInstanceNotFoundException("Custom storage manager not found:" + customType + ", please check your config");
            }
        }

        if (storageManager == null) {
            throw new StorageInstanceNotFoundException(integrateConfig.getStorageType().name());
        }
        return storageManager;
    }


    @Override
    public String getName() {
        return INTEGRATE.name();
    }

    @Override
    public Credentials credentials(long durationSeconds) {
        return storageManager.credentials(durationSeconds);
    }
}
